<?php
// $Id: api.inc $

session_start();
require_once "oauth.inc.php";


/**
 * @file
 * MYOWS API wrapper (JSON)
 * If you wish to use this class without Drupal, add three functions named "variable_get", "variable_set" and "variable_del".
 * @see http://myows.com/info/api/
 */
class MYOWS {


	/**
	 * Configuration: Application Credentials.
	 * You can get your own at https://myows.com/api_v1/oauth/register_application
	 */
	const KEY = '17b8649b983a00644cb4768a726d62ad04becf9fa';
	const SECRET = '7f5fbc31eaf3f28dbce482ee7ae9b1e7';


	/**
	 * File extensions that generate image thumbnails.
	 */
	static public $EXT_IMAGE = array(".jpg", ".gif", ".png");

	/**
	 * File extensions that are plain text (or html code).
	 */
	static public $EXT_TEXT = array(".txt", ".csv", ".html", ".htm");

	/**
	 * File extensions that are raw text.
	 */
	static public $EXT_TEXT_RAW = array(".txt", ".csv");


	/**
	 * Default list of category names.
	 */
	static public $DEFAULT_CATEGORIES = array("none", "animation", "blog article", "blueprint", "copy/text", "illustration", "logo", "mock-up", "photograph", "plan", "song", "track", "website");

	/**
	 * Default list of client names.
	 */
	static public $DEFAULT_CLIENTS = array("none", "self");


	/**
	 * Performs a OAuth request for an "ows" method and returns the JSON response.
	 * This requires to have permanent tokens.
	 * @param	$call		String		API method to call (example: "listOws" )
	 * @param	$method		String		Method using which to send the request ("GET", "POST" or "PUT")
	 * @param	$params		Array		Optional parameters (example: array("id" => "123") )
	 */
	static private function request($call, $method = 'GET', $params = NULL){
		// Don't even try to send the request unless we have permanent tokens
		if (!MYOWS::logged()) return array();

		// Calculate the endpoint
		$tmp = array($call);
		if (($method == 'GET') /*|| ($method == 'PUT')*/) {
			if (is_array($params)){
				foreach ($params as $key => $value){
					if (!empty($value)){
						$tmp[] = $key;
						$tmp[] = $value;
					}
				}
			}
			$params = NULL;
		}
		$endpoint = 'https://myows.com/api_v1/ows/'. implode('/', $tmp) .'/format/json/';

		// Build the request
		$client = new OAuthConsumer(MYOWS::KEY, MYOWS::SECRET, NULL);
		$token = new OAuthToken(variable_get('myows_token', null), variable_get('myows_secret', null));
		$request = OAuthRequest::from_consumer_and_token($client, $token, $method, $endpoint, NULL);
		$request->sign_request(new OAuthSignatureMethod_HMAC_SHA1(), $client, $token);

		// Setup cURL and send the request
		$curl = curl_init($endpoint);
		curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($curl, CURLOPT_FAILONERROR, false);
		curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
		curl_setopt($curl, CURLOPT_HTTPHEADER, array($request->to_header()));
		if ($method == 'POST') curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
		/*else if ($method == 'PUT'){
			curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT');
			curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
			//curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($params));
		}*/

		// Parse the response
		return json_decode(curl_exec($curl), true);
	}



	/**
	 * If we just started the login process (or if the autorization failed at the last request)
	 * this function retrieves temporary credentials to (re)try authentification.
	 */
	static private function getTempToken() { //was authoriseRedirect()
		$endpoint = 'https://myows.com/api_v1/oauth/request_token';

		// Build the request
		$client = new OAuthConsumer(MYOWS::KEY, MYOWS::SECRET, NULL);  
		$request = OAuthRequest::from_consumer_and_token($client, NULL, 'GET', $endpoint, NULL);  
		$request->sign_request(new OAuthSignatureMethod_HMAC_SHA1(), $client, NULL);  

		// Initialize a cURL session  
		$curl = curl_init($endpoint);    
		curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($curl, CURLOPT_FAILONERROR, false);
		curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
		curl_setopt($curl, CURLOPT_HTTPHEADER, array($request->to_header()));     
		$response = curl_exec($curl);    
		curl_close($curl);    

		// Extract the temporary credentials and stores them
		parse_str($response, $tokens);
		$oauth_token = $tokens['oauth_token'];
		$oauth_token_secret = $tokens['oauth_token_secret'];	
		variable_set('myows_token_temp', $oauth_token);
		variable_set('myows_secret_temp', $oauth_token_secret);
		
		// Calculate the callback
		$oauth_callback = 'http';
		if ($_SERVER["HTTPS"] == "on") $oauth_callback .= "s";
		$oauth_callback .= "://";
		if ($_SERVER["SERVER_PORT"] != "80") $oauth_callback .= $_SERVER["HTTP_HOST"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
		else $oauth_callback .= $_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"];
		$oauth_callback = explode("?", $oauth_callback);
		$oauth_callback = urlencode($oauth_callback[0]);

		$auth_url = 'https://myows.com/api_v1/oauth/authorize?oauth_token=' . $oauth_token . '&oauth_callback=' . $oauth_callback;

		// Sends the user to MYOWS for autorization.
		// Calling MYOWS::login() before the headers are sent is much cleaner, you should do that when you have a choice.
		if (headers_sent()) {
			echo '<a href="'.$auth_url.'">Click here to authorize at MYOWS</a>';
		} else {
			header("Location: $auth_url");
			exit();
		}
	}



	/* 
	 * This function is called once the temporary credentials passed to myows when requesting authorisation have been authorised. 
	 * It exchanges them for token credentials, which can then be used for all further requests for that user.
	 */
	static private function getRealTokenFromTemp(){
		$oauth_token = variable_get('myows_token_temp', null);
		$oauth_token_secret = variable_get('myows_secret_temp', null);
		$endpoint = 'https://myows.com/api_v1/oauth/access_token';

		// Build the request
		$token = new OAuthToken($oauth_token, $oauth_token_secret);
		$client = new OAuthConsumer(MYOWS::KEY, MYOWS::SECRET, NULL);
		$request = OAuthRequest::from_consumer_and_token($client, $token, 'GET', $endpoint, NULL);
		$request->sign_request(new OAuthSignatureMethod_HMAC_SHA1(), $client, $token);

		// Initialize a cURL session
		$curl = curl_init($endpoint);    
		curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($curl, CURLOPT_FAILONERROR, false);
		curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
		curl_setopt($curl, CURLOPT_HTTPHEADER, array($request->to_header()));

		// Get response
		$response = curl_exec($curl);
		if (strpos($response, "Verification Failed") !== false) return false;
		parse_str($response,$tokens);

		// Store the permanent token credentials
		variable_set('myows_token', $tokens['oauth_token']);
		variable_set('myows_secret', $tokens['oauth_token_secret']);

		// Remove the temporary credentials, they are no longer needed
		variable_del('myows_token_temp');
		variable_del('myows_secret_temp');

		return true;
	}


	/**
	 * Returns true if we have permanent tokens (required for "ows" requests),
	 * false otherwise (temporary tokens, no token or logged out: you can only make "auth" requests).
	 */
	static public function logged(){
		$token = variable_get('myows_token', null);
		return isset($token);
	}


	/**
	 * Gets the application authorized by MYOWS if needed.
	 */
	static public function login() {
		if (MYOWS::logged()) {
			return;
		} else {
			$token = variable_get('myows_token_temp', null);
			if (isset($token)) {
				if (MYOWS::getRealTokenFromTemp()) return;
				else MYOWS::getTempToken(); //it refused to give a real token, so we get another temporary token and retry
			} else {
				MYOWS::getTempToken(); //no permanent nor temporary token
			}
		}
	}


	/**
	 * If signing out, for the purposes of this demo just clear all temporary
	 * or token credentials remembered in this session.
	 * I could use it for "unlink plugin" or "use another user".
	 */
	static public function logout() {
		variable_del('myows_token');
		variable_del('myows_secret');
		variable_del('myows_token_temp');
		variable_del('myows_secret_temp');
	}


	/**
	 * Returns the list of OWS matching the optional filters.
	 * @param	search_string	String		Filter by search query
	 * @param	case_filter		String		Filter by type of case ("active","solved")
	 * @param	sort_by			String		Sorting ("created", "title", "type", "client", "category", "size")
	 * @param	offset			Integer		The offset to return the search results from
	 * @param	limit			Integer		Number of results to return
	 */
	static public function listOws($search_string = '', $case_filter = '', $sort_by = '', $offset = 0, $limit = 0) {
		return MYOWS::request(
			'listOWS',
			'GET',
			array(   // associative array
				'search_string' => $search_string,
				'case_filter' => $case_filter,
				'sort_by' => $sort_by,
				'sort_by' => $sort_by,
				'limit' => $limit
			)
		);
	}


	/**
	 * Retrieves detailed infomations about a specific OW.
	 * @param	$id			Integer		ID of the OW
	 */
	static public function owInfo($id){
		return MYOWS::request(
			'owInfo',
			'GET',
			array(
				'id' => $id
			)
		);
	}


	/**
	 * Retrieves a time-limited S3 (Amazon CDN) URL you can download the OW at.
	 * @param	$id			Integer		ID of the OW
	 */
	static public function downloadOw($id){
		return MYOWS::request(
			'downloadOw',
			'GET',
			array(
				'id' => $id
			)
		);
	}


	/**
	 * Retrieves a time-limited S3 (Amazon CDN) URL for a specific attachment.
	 * You can get the list of attachments of an OW using "listOws" or "owInfo".
	 * @param	$attachment_id		Integer		ID of the attached file
	 */
	static public function downloadAttachment($attachment_id){
		return MYOWS::request(
			'downloadAttachment',
			'GET',
			array(
				'attachment_id' => $attachment_id
			)
		);
	}

	
	/**
	 * Edits the informations of a specific OW (but does not modify the actual file).
	 * @param	$id					Integer
	 * @param	$name				String		Name of the OW
	 * @param	$description		String		Description for this OW
	 * @param	$category			String		Category under which this OW is filed
	 * @param	$client				String		Client this OW is for
	 */
	static public function editOW($id, $name, $description, $category, $client){
		return MYOWS::request(
			'editOW',
			'POST',
			array(
				'id' => $id,
				'ow_name' => $name,
				'category' => $category,
				'client' => $client,
				'description' => $description
			)
		);
	}


	/**
	 * Sends an OW certificate by email.
	 * @param	$id			Integer		ID of the OW
	 * @param	email		String		Email address to send the centificate to
	 * @param	$to			String		Name of the perpetrator concerned
	 * @param	$from		String		Name of the person sending the certificate
	 * @important This function doesn't work: the API doesn't return any data, not even an error message :-(
	 */
	static public function sendOWCert($id, $email, $to, $from){
		return MYOWS::request(
			'editOW',
			'POST',
			array(
				'id' => $id,
				'email' => $email,
				'perpetrator_name' => $to,
				'to_name' => $from
			)
		);
	}


	/**
	 * Changes the password of an OW.
	 * @param	$id			Integer		ID of the OW whose password to modify
	 * @param	$password	String		New password for the OW
	 */
	static public function changeOWPass($id, $password){
		return MYOWS::request(
			'changeOWPass',
			'POST',
			array(
				'id' => $id,
				'ow_pass' => $password
			)
		);
	}


	/**
	 * Uploads raw text contents to MYOWS.
	 * @param	$id				String		Client-generated 15 character unique alphanumeric string (for "uploadOWProgress" calls)
	 * @param	$data			String		Text contents of the OW to upload
	 * @param	$name			String		Name of the OW
	 * @param	$description	String		Description for this OW
	 * @param	$category		String		Category under which this OW is filed
	 * @param	$client			String		Client this OW is for
	 * @important This function doesn't work: the API doesn't return any data, not even an error message :-(
	 */
	static public function uploadTextOW($id, $data, $name, $description, $category, $client) {
		return MYOWS::request(
			'uploadOW',
			'POST',
			array(
				'type' => "text",
				'ow_name' => $name,
				'category' => $category,
				'client' => $client,
				'description' => $description,
				'UPLOAD_IDENTIFIER' => $id,
				'flat_text' => $data
			)
		);
	}


	/**
	 * Uploads a file to MYOWS.
	 * @param	$id					String		Client-generated 15 character unique alphanumeric string (for "uploadOWProgress" calls)
	 * @param	$data				String		Binary contents of the file to upload (you can also use "@absolute/path/to/file")
	 * @param	$name				String		Name of the OW
	 * @param	$description		String		Description for this OW
	 * @param	$category			String		Category under which this OW is filed
	 * @param	$client				String		Client this OW is for
	 */
	static public function uploadFileOW($id, $data, $name, $description, $category, $client){
		return MYOWS::request(
			'uploadOW',
			'POST',
			array(
				'type' => "file",
				'ow_name' => $name,
				'category' => $category,
				'client' => $client,
				'description' => $description,
				'UPLOAD_IDENTIFIER' => $id,
				'register_file' => $data
			)
		);
	}

	
	/**
	 * Checks the status of an OW currently uploading via "uploadTextOW" or "uploadFileOW".
	 * @param	$id					String		Unique ID of the upload (same value as "$id" from "uploadTextOW" and "uploadFileOW")
	 */
	static public function uploadOWProgress($id){
		return MYOWS::request(
			'uploadOWProgress',
			'POST',
			array(
				'file_id' => $id
			)
		);
	}

}

?>